﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace JGSY.Tasks
{
    public static class Monitor1
    {
        // 共享资源
        private static int sharedResource = 0;
        // 锁对象
        private static readonly object lockObject = new object();
        // 条件变量
        private static readonly object conditionLock = new object();
        private static bool condition = false;

        public static void Monitor001()
        {
            // 演示lock关键字的使用
            Console.WriteLine("=== 使用lock关键字保护临界区 ===");
            RunLockExample();

            // 演示Monitor类的底层实现
            Console.WriteLine("\n=== 使用Monitor类手动实现临界区保护 ===");
            RunMonitorExample();

            // 演示Monitor类所有属性和方法的应用
            Console.WriteLine("\n=== Monitor类完整功能演示 ===");
            RunFullMonitorExample();

            Console.WriteLine("\n所有示例执行完毕，按任意键退出...");
            Console.ReadKey();
        }

        static void RunLockExample()
        {
            var tasks = new Task[5];
            for (int i = 0; i < 5; i++)
            {
                tasks[i] = Task.Run(() =>
                {
                    for (int j = 0; j < 1000; j++)
                    {
                        // lock关键字的底层实现是基于Monitor.Enter/Exit
                        lock (lockObject)
                        {
                            sharedResource++;
                        }
                    }
                });
            }

            Task.WaitAll(tasks);
            Console.WriteLine($"Lock保护后的共享资源值: {sharedResource}");
            sharedResource = 0; // 重置共享资源
        }

        static void RunMonitorExample()
        {
            var tasks = new Task[5];
            for (int i = 0; i < 5; i++)
            {
                tasks[i] = Task.Run(() =>
                {
                    for (int j = 0; j < 1000; j++)
                    {
                        // 手动实现lock的功能
                        bool lockTaken = false;
                        try
                        {
                            // 尝试获取锁，可设置超时
                            Monitor.Enter(lockObject, ref lockTaken);
                            sharedResource++;
                        }
                        finally
                        {
                            // 确保锁一定会被释放
                            if (lockTaken)
                                Monitor.Exit(lockObject);
                        }
                    }
                });
            }

            Task.WaitAll(tasks);
            Console.WriteLine($"Monitor保护后的共享资源值: {sharedResource}");
            sharedResource = 0; // 重置共享资源
        }

        static void RunFullMonitorExample()
        {
            // 演示Monitor类的完整功能
            var producer = Task.Run(() => ProduceItems());
            var consumer = Task.Run(() => ConsumeItems());

            Task.WaitAll(producer, consumer);
        }

        static void ProduceItems()
        {
            for (int i = 0; i < 5; i++)
            {
                // 模拟生产时间
                Thread.Sleep(200);

                // 获取锁
                Monitor.Enter(conditionLock);
                try
                {
                    // 生产一个项目
                    Console.WriteLine($"生产者生产了项目 {i}");
                    sharedResource++;

                    // 设置条件
                    condition = true;

                    // 唤醒等待的消费者
                    Monitor.Pulse(conditionLock);

                    // 输出锁状态
                    Console.WriteLine($"锁是否被当前线程持有: {Monitor.IsEntered(conditionLock)}");
                }
                finally
                {
                    // 释放锁
                    Monitor.Exit(conditionLock);
                }
            }
        }

        static void ConsumeItems()
        {
            for (int i = 0; i < 5; i++)
            {
                // 获取锁
                Monitor.Enter(conditionLock);
                try
                {
                    // 检查条件，如果不满足则等待
                    while (!condition)
                    {
                        Console.WriteLine("消费者等待中...");
                        // 释放锁并等待
                        Monitor.Wait(conditionLock);
                    }

                    // 消费一个项目
                    Console.WriteLine($"消费者消费了项目 {sharedResource - 1}");
                    sharedResource--;

                    // 重置条件
                    condition = false;

                    // 检查锁是否被当前线程持有
                    bool isLocked = Monitor.IsEntered(conditionLock);
                    Console.WriteLine($"锁是否被当前线程持有: {isLocked}");

                    // 演示TryEnter带超时
                    bool acquired = Monitor.TryEnter(conditionLock, 100);
                    if (acquired)
                    {
                        Console.WriteLine("获取锁成功（TryEnter带超时）");
                        Monitor.Exit(conditionLock);
                    }
                    else
                    {
                        Console.WriteLine("获取锁超时（TryEnter带超时）");
                    }
                }
                finally
                {
                    // 释放锁
                    Monitor.Exit(conditionLock);
                }

                // 模拟消费时间
                Thread.Sleep(100);
            }
        }
    }
}
